﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
//using System.Windows.Forms;
using System.Xml;
using System.Threading;

/// <summary>
/// 这个文件包含了工业上常用的一些组件
/// 延迟,上升沿,下降沿,RS等.
/// 消息管理器
/// </summary>
namespace IndustryWrapper
{
    #region 高精度定时器-利用频率计算
    /// <summary>
    /// 定时器委托事件的参数
    /// </summary>
    public class TimerEventArgs : EventArgs
    {
        private long clockFrequency;
        public long ClockFrequency
        {
            get { return clockFrequency; }
            set { clockFrequency = value;}
        }
        private long previousTickCount;
        public long PreviousTickOunt
        {
            get { return previousTickCount; }
            set { previousTickCount = value; }
        }

        private long currentTickCount;
        public long CurrentTickCount
        {
            get { return currentTickCount; }
            set { currentTickCount = value; }
        }

        public TimerEventArgs(long clockFreq, long prevTick, long currTick)
        {
            this.clockFrequency = clockFreq;
            this.previousTickCount = prevTick;
            this.currentTickCount = currTick;
        }
        public TimerEventArgs()
        {
            this.clockFrequency = 0;
            this.previousTickCount = 0;
            this.currentTickCount = 0;
        }
    }
    /// <summary>
    /// 高精度定时器事件委托
    /// </summary>
    public delegate void HighTimerEventHandler(object sender, TimerEventArgs e);

    /// <summary>
    ///  高精度定时器利用Kernel32的QueryPerformanceCounter提高定时精度
    /// </summary>
    public class HighPrecisionTimer
    {
        //高精度定时器都必须保存在这个列表中,后续自动卸载
        public static List<HighPrecisionTimer> list = new List<HighPrecisionTimer>();
        #region 调用系统函数
        [DllImport("Kernel32.dll")]
        private static extern bool QueryPerformanceCounter(out long lpPerformanceCount);

        [DllImport("Kernel32.dll")]
        private static extern bool QueryPerformanceFrequency(out long lpFrequency);
        #endregion
        public event HighTimerEventHandler TimeOut;

        private Thread thread = null;
        private object threadLock = new object();

        private static long clockFrequency = 0;
        private long intevalTicks = 0;
        private long nextTriggerTime = 0;
        private TimerEventArgs timeEventAgrs = new TimerEventArgs();
        private int intervalMs;
        public int id;
        static HighPrecisionTimer()
        {
            QueryPerformanceFrequency(out clockFrequency);
        }
        /// <summary>
        /// 自动卸载所有定时器
        /// </summary>
        public static void DestroyAll()
        {
            foreach (var item in list)
            {
                item.Destroy();
            }
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        public HighPrecisionTimer(int id)
        {
            if (clockFrequency == 0)
            {
                return;
            }
            this.intervalMs = 1000;
            this.enable = false;

            //thread = new Thread(new ThreadStart(ThreadProc));
            //thread.Name = "HighAccuracyTimer";
            //thread.Priority = ThreadPriority.Highest;
            //thread.Start();
            list.Add(this);
        }
        /// <summary>
        /// 定时器间隔
        /// </summary>
        public int Interval
        {
            get
            {
                return intervalMs;
            }
            set
            {
                if (value >= 1)
                {
                    intervalMs = value;
                    intevalTicks = (long)(((double)intervalMs / (double)1000) * (double)clockFrequency);
                }
            }
        }

        private bool enable;
        private bool canrun = false;
        /// <summary>
        /// 启动定时器标志
        /// </summary>
        public bool Enabled
        {
            get
            {
                return enable;
            }
            set
            {
                enable = value;
                if (value == true)
                {
                    intevalTicks = (long)(((double)intervalMs / (double)1000) * (double)clockFrequency);
                    //long currTick = 0;
                    //GetTick(out currTick);
                    //nextTriggerTime = currTick + intevalTicks;
                    if (thread == null)
                    {
                        thread = new Thread(new ThreadStart(ThreadProc));
                        thread.Name = "HighAccuracyTimer";
                        thread.Priority = ThreadPriority.Highest;
                        thread.Start();
                    }
                }
                else
                {
                    Destroy();
                }
            }
        }

        /// <summary>
        /// 进程主程序
        /// </summary>
        private void ThreadProc()
        {
            canrun = true;
            long currTime;
            GetTick(out currTime);
            nextTriggerTime = currTime + intevalTicks;
            while (canrun)
            {
                while (currTime < nextTriggerTime)
                {
                    GetTick(out currTime); //决定时钟的精度
                }
                nextTriggerTime = currTime + intevalTicks;

                if (TimeOut != null && enable == true)
                {
                    timeEventAgrs.ClockFrequency = clockFrequency;
                    timeEventAgrs.PreviousTickOunt = currTime - intevalTicks;
                    timeEventAgrs.CurrentTickCount = currTime;
                    TimeOut(this, timeEventAgrs);
                }
            }
        }
        /// <summary>
        /// 获得当前时钟计数
        /// </summary>
        /// <param name="currentTickCount">时钟计数</param>
        /// <returns>获得是否成功</returns>
        private bool GetTick(out long currentTickCount)
        {
            if (QueryPerformanceCounter(out currentTickCount) == false)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        /// <summary>
        /// 注销定时器
        /// </summary>
        public void Destroy()
        {
            enable = false;
            canrun = false;
            if (thread != null && thread.IsAlive)
            {
                thread.Abort();
                while (thread.IsAlive)
                {
                    Thread.Sleep(1);
                }
            }
            thread = null;
        }
    }
    #endregion
    #region 加密
    /// <summary>
    /// 机器的序列号信息
    /// </summary>
    public class CSerialData
    {
        public string sn = "";//序列号
        public string macSN = "";//机器码
        public string startTime = "";//启动时间
    }
    /// <summary>
    /// 机器锁,时间锁,可以设定有效期.
    /// 这里是通过网卡得物理地址来加密的
    /// </summary>
    public class CMachLockByMac : CSerialNumberBase
    {
        public override string MC_GetSn(string machSN, int days, bool type)
        {
            if (type)
            {
                string uid = machSN;
                //获取天数
                DateTime dt1 = Convert.ToDateTime("2020-1-1");
                DateTime dt2 = DateTime.Now;
                int dayCount = Convert.ToInt32((dt2 - dt1).TotalDays) - 1 + days;

                uid += dayCount.ToString();

                MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
                string t2 = BitConverter.ToString(md5.ComputeHash(UTF8Encoding.Default.GetBytes(uid)), 4, 8);
                t2 = t2.Replace("-", "");
                return t2.ToUpper();
            }
            else
            {
                string uid = machSN;

                int dayCount = days;

                uid += dayCount.ToString();

                MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
                string t2 = BitConverter.ToString(md5.ComputeHash(UTF8Encoding.Default.GetBytes(uid)), 4, 8);
                t2 = t2.Replace("-", "");
                return t2.ToUpper();
            }
        }
        public override string MC_GetMachSN()
        {
            //获取所有的MAC地址
            string uid = CMacAddressHelper.GetMacByIpConfig();
            if (uid != "")
            {
                uid += "TDYDIY";//自己加一点
                MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
                string t2 = BitConverter.ToString(md5.ComputeHash(UTF8Encoding.Default.GetBytes(uid)), 4, 8);
                t2 = t2.Replace("-", "");
                string machSN = t2.ToUpper();
                return machSN;
            }
            else
            {
                return "";
            }
        }
        public override bool MC_CanRun(string userSn, string machSN, ref int haveDays)
        {
            int canUsedDays = -1;
            CSerialNumberBase app = this as CSerialNumberBase;
            haveDays = 0;
            for (int i = 0; i < 99999; i++)
            {
                if (app.MC_GetSn(machSN, i, false) == userSn)
                {
                    canUsedDays = i;
                    break;
                }
            }
            if (canUsedDays < 0) return false;
            if (canUsedDays == 0) return true;
            if (canUsedDays > 0)
            {
                //获取天数
                DateTime dt1 = Convert.ToDateTime("2020-1-1");
                DateTime dt2 = DateTime.Now;
                int dayCount = Convert.ToInt32((dt2 - dt1).TotalDays) - 1;
                haveDays = Math.Abs(dayCount - canUsedDays);
                if (dayCount <= canUsedDays) return true;
                else return false;
            }
            return false;
        }
        public override void MC_SaveSnFile(CSerialData data, string xml)
        {
            try
            {
                //文档
                XmlWriterSettings set = new XmlWriterSettings();
                set.Indent = true;
                set.NewLineOnAttributes = false;
                XmlWriter writer = XmlWriter.Create(xml, set);
                //master
                writer.WriteStartDocument();
                writer.WriteStartElement("SN");
                writer.WriteElementString("MachSN", data.macSN);
                writer.WriteElementString("AuthorizeSN", data.sn);
                writer.WriteElementString("StartTime", data.startTime);
                writer.WriteEndElement();
                writer.WriteEndDocument();
                writer.Flush();
                writer.Close();
            }
            catch (Exception)
            {
            }
        }
        public override CSerialData MC_ReadSnFile(string xml)
        {
            CSerialData tmpdata = new CSerialData();
            XmlDocument doc = new XmlDocument();
            try
            {
                doc.Load(xml);
                //解析XML文件
                if (doc != null)
                {
                    XmlElement root = doc.DocumentElement;
                    if (root != null && root.Name == "SN")
                    {
                        //内参读取
                        XmlNode snNode = root.SelectSingleNode("/SN/AuthorizeSN");
                        if (snNode != null)
                        {
                            tmpdata.sn = snNode.InnerText;
                        }
                        XmlNode snNode2 = root.SelectSingleNode("/SN/MachSN");
                        if (snNode2 != null)
                        {
                            tmpdata.macSN = snNode2.InnerText;
                        }
                        XmlNode snNode3 = root.SelectSingleNode("/SN/StartTime");
                        if (snNode3 != null)
                        {
                            tmpdata.startTime = snNode3.InnerText;
                        }
                    }
                }
                return tmpdata;
            }
            catch (Exception)
            {
                return tmpdata;
            }
        }
    }
    /// <summary>
    /// Mac地址获取帮助类
    /// </summary>
    class CMacAddressHelper
    {
        ///<summary>
        /// 根据截取ipconfig /all命令的输出流获取网卡Mac，支持不同语言编码
        ///</summary>
        ///<returns></returns>
        public static string GetMacByIpConfig()
        {
            List<string> macs = new List<string>();

            var runCmd = Cmd.RunCmd("chcp 437&&ipconfig/all");

            foreach (var line in runCmd.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries).Select(l => l.Trim()))
            {
                if (!string.IsNullOrEmpty(line))
                {
                    if (line.StartsWith("Physical Address"))
                    {
                        macs.Add(line.Substring(36));
                    }
                    else if (line.StartsWith("DNS Servers") && line.Length > 36 && line.Substring(36).Contains("::"))
                    {
                        macs.Clear();
                    }
                    else if (macs.Count > 0 && line.StartsWith("NetBIOS") && line.Contains("Enabled"))
                    {
                        return macs.Last();
                    }
                }
            }

            return macs.FirstOrDefault();
        }

        ///<summary>
        /// 通过WMI读取系统信息里的网卡MAC
        ///</summary>
        ///<returns></returns>
        public static List<string> GetMacByWmi()
        {
            try
            {
                List<string> macs = new List<string>();
                ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
                ManagementObjectCollection moc = mc.GetInstances();
                foreach (ManagementObject mo in moc)
                {
                    if ((bool)mo["IPEnabled"])
                    {
                        var mac = mo["MacAddress"].ToString();
                        macs.Add(mac);
                    }
                }
                return macs;
            }
            catch (Exception)
            {
                return null;
            }
        }

        ///<summary>
        /// 通过NetworkInterface读取网卡Mac
        ///</summary>
        ///<returns></returns>
        public static List<string> GetMacByNetworkInterface()
        {
            List<string> macs = new List<string>();
            NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
            foreach (NetworkInterface ni in interfaces)
            {
                macs.Add(ni.GetPhysicalAddress().ToString());
            }
            return macs;
        }

        ///<summary>
        /// 通过SendARP获取网卡Mac
        /// 网络被禁用或未接入网络（如没插网线）时此方法失灵
        ///</summary>
        ///<param name="remoteIP"></param>
        ///<returns></returns>
        public static string GetMacBySendArp(string remoteIP)
        {
            StringBuilder macAddress = new StringBuilder();
            try
            {
                Int32 remote = inet_addr(remoteIP);
                Int64 macInfo = new Int64();
                Int32 length = 6;
                SendARP(remote, 0, ref macInfo, ref length);
                string temp = Convert.ToString(macInfo, 16).PadLeft(12, '0').ToUpper();
                int x = 12;
                for (int i = 0; i < 6; i++)
                {
                    if (i == 5)
                    {
                        macAddress.Append(temp.Substring(x - 2, 2));
                    }
                    else
                    {
                        macAddress.Append(temp.Substring(x - 2, 2) + "-");
                    }
                    x -= 2;
                }
                return macAddress.ToString();
            }
            catch
            {
                return macAddress.ToString();
            }
        }

        [DllImport("Iphlpapi.dll")]
        private static extern int SendARP(Int32 dest, Int32 host, ref Int64 mac, ref Int32 length);
        [DllImport("Ws2_32.dll")]
        private static extern Int32 inet_addr(string ip);

        class Cmd
        {
            private static string CmdPath = @"C:\Windows\System32\cmd.exe";
            /// <summary>
            /// 执行cmd命令 返回cmd窗口显示的信息
            /// 多命令请使用批处理命令连接符：
            /// <![CDATA[
            /// &:同时执行两个命令
            /// |:将上一个命令的输出,作为下一个命令的输入
            /// &&：当&&前的命令成功时,才执行&&后的命令
            /// ||：当||前的命令失败时,才执行||后的命令]]>
            /// </summary>
            /// <param name="cmd">执行的命令</param>
            public static string RunCmd(string cmd)
            {
                cmd = cmd.Trim().TrimEnd('&') + "&exit";//说明：不管命令是否成功均执行exit命令，否则当调用ReadToEnd()方法时，会处于假死状态
                using (Process p = new Process())
                {
                    p.StartInfo.FileName = CmdPath;
                    p.StartInfo.UseShellExecute = false;        //是否使用操作系统shell启动
                    p.StartInfo.RedirectStandardInput = true;   //接受来自调用程序的输入信息
                    p.StartInfo.RedirectStandardOutput = true;  //由调用程序获取输出信息
                    p.StartInfo.RedirectStandardError = true;   //重定向标准错误输出
                    p.StartInfo.CreateNoWindow = true;          //不显示程序窗口
                    p.Start();//启动程序

                    //向cmd窗口写入命令
                    p.StandardInput.WriteLine(cmd);
                    p.StandardInput.AutoFlush = true;

                    //获取cmd窗口的输出信息
                    string output = p.StandardOutput.ReadToEnd();
                    p.WaitForExit();//等待程序执行完退出进程
                    p.Close();

                    return output;
                }
            }
        }
    }
    /// <summary>
    /// 自定义的一些功能
    /// </summary>
    public class CSerialNumberBase
    {
        //数据
        private CSerialData data = new CSerialData();
        /// <summary>
        /// 获取机器吗
        /// </summary>
        /// <returns></returns>
        public virtual string MC_GetMachSN()
        {
            return "";
        }
        /// <summary>
        /// 获取序列号 这个序列号是给用户输入的.包含了可以使用的天数.
        /// </summary>
        /// <param name="machSN">机器码</param>
        /// <param name="days">执行天数</param>
        /// <param name="type">类型</param>
        /// <returns></returns>
        public virtual string MC_GetSn(string machSN, int days = 30, bool type = true)
        {
            return "";
        }
        /// <summary>
        /// 读取保存的序列号文档
        /// </summary>
        /// <param name="xml"></param>
        /// <returns></returns>
        public virtual CSerialData MC_ReadSnFile(string xml = @"Confige\SN.xml")
        {
            return null;
        }
        /// <summary>
        /// 把当前的数据保存起来
        /// </summary>
        /// <param name="data"></param>
        /// <param name="xml"></param>
        public virtual void MC_SaveSnFile(CSerialData data, string xml = @"Confige\SN.xml")
        {

        }
        /// <summary>
        /// 输入序列号,判断是否可以运行,还剩余多少天.
        /// </summary>
        /// <param name="userSn"></param>
        /// <param name="machSN"></param>
        /// <param name="haveDays"></param>
        /// <returns></returns>
        public virtual bool MC_CanRun(string userSn, string machSN, ref int haveDays)
        {
            return false;
        }
    }
    #endregion
    #region 用户管理
    /// <summary>
    /// 用户等级
    /// </summary>
    public enum EUserLevel
    {
        Operate=0,  //操作工
        MachManager=1,//机器维护人员
        SysEngine=2 //最高等级 所有都可以
    }
    /// <summary>
    /// 用户管理器
    /// </summary>
    public static class CUserManager
    {
        public static List<string> errlist = new List<string>();
        public static int index = -1;//0=opt 1=maintain 2=sysdevelop
        public static int level = -1;
        private static List<string> opt = new List<string>();//操作工密码集合
        private static List<string> maintain = new List<string>();//维护人员密码集合
        private static List<string> sysdevelop = new List<string>();//系统维护人
        private static object lockObj = new object();
        static CUserManager()
        {
            if(!Read())
            {
                System.Windows.Forms.MessageBox.Show("读取用户文件失败!");
            }
        }
        public static string getUser(ref string name,ref string optLevel)
        {
            lock (lockObj)
            {
                string rtstr = "";
                if (index == -1 && level == -1)
                {
                    name = "操作员";
                    optLevel = "默认用户";
                    rtstr = name + ":" + optLevel;
                    return rtstr;
                }
                switch (level)
                {
                    case 0:
                        if (index >=0 && index < opt.Count)
                        {
                            name = "操作员:";
                            optLevel = opt[index];
                            rtstr = name + ":" + optLevel;
                        }
                        break;
                    case 1:
                        if (index >= 0 && index < maintain.Count)
                        {
                            name = "设备维护:";
                            optLevel = maintain[index];
                            rtstr = name + ":" + "****";
                        }
                        break;
                    case 2:
                        if (index >= 0 && index < sysdevelop.Count)
                        {
                            name = "系统维护:";
                            optLevel = sysdevelop[index];
                            rtstr = name + ":" + "*****";
                        }
                        break;
                }
                return rtstr;
            }
        }
        public static string getUser()
        {
            lock (lockObj)
            {
                string name = "";
                string optLevel = "";
                string rtstr = "";
                if (index == -1 && level == -1)
                {
                    name = "操作员";
                    optLevel = "默认用户";
                    rtstr = name + ":" + optLevel;
                    return rtstr;
                }
                switch (level)
                {
                    case 0:
                        if (index >= 0 && index < opt.Count)
                        {
                            name = "操作员:";
                            optLevel = opt[index];
                            rtstr = name + ":" + optLevel;
                        }
                        break;
                    case 1:
                        if (index >= 0 && index < maintain.Count)
                        {
                            name = "设备维护:";
                            optLevel = maintain[index];
                            rtstr = name + ":" + "****";
                        }
                        break;
                    case 2:
                        if (index >= 0 && index < sysdevelop.Count)
                        {
                            name = "系统维护:";
                            optLevel = sysdevelop[index];
                            rtstr = name + ":" + "*****";
                        }
                        break;
                }
                return rtstr;
            }
        }
        public static EUserLevel LevelNow
        {
            get
            {
                switch (level)
                {
                    case 0:
                        return EUserLevel.Operate;
                    case 1:
                        return EUserLevel.MachManager;
                    case 2:
                        return EUserLevel.SysEngine;
                    default:
                        return EUserLevel.Operate;
                }
            }
        }
        /// <summary>
        /// 检测用户密码
        /// </summary>
        /// <param name="lv">0=普通用户 1=设备维护人员 2=系统维护人员</param>
        /// <param name="password"></param>
        /// <returns></returns>
        public static bool setUser(int lv,string password)
        {
            lock (lockObj)
            {
                if (password == "")
                    return false;
                switch (lv)
                {
                    case 0:
                        for (int i = 0; i < opt.Count; i++)
                        {
                            if (password == opt[i])
                            {
                                index = i;
                                level = 0;
                                return true;
                            }
                        }
                        break;
                    case 1:
                        for (int i = 0; i < maintain.Count; i++)
                        {
                            if (password == maintain[i])
                            {
                                index = i;
                                level = 1;
                                return true;
                            }
                        }
                        break;
                    case 2:
                        for (int i = 0; i < sysdevelop.Count; i++)
                        {
                            if (password == sysdevelop[i])
                            {
                                index = i;
                                level = 2;
                                return true;
                            }
                        }
                        break;
                }
                return false;
            }
        }

        private static void clear()
        {
            opt.Clear();
            maintain.Clear();
            sysdevelop.Clear();
        }
        /// <summary>
        /// 设置默认用户
        /// </summary>
        public static void setDefaultUser()
        {
            index = -1;
            level = -1;
        }
        /// <summary>
        /// 从文件中读取用户配置
        /// </summary>
        /// <param name="xml">文件名</param>
        /// <returns>读取正常异常</returns>
        public static bool Read(string xml = @"confige/Users.xml")
        {
            try
            {
                clear();
                //解析XML文件
                XmlDocument doc = new XmlDocument();
                doc.Load(xml);
                if (doc != null)
                {
                    XmlElement root = doc.DocumentElement;
                    if (root != null && root.Name == "Users")
                    {
                        //刀库状态
                        XmlNode node = root.SelectSingleNode("/Users/操作员");
                        if (node != null)
                        {
                            for (int i = 0; i < node.ChildNodes.Count; i++)
                            {
                                //先转换 如果成功再加入
                                try
                                {
                                    if(node.ChildNodes[i].Name != "")
                                        opt.Add(node.ChildNodes[i].Name);
                                }
                                catch (Exception)
                                {
                                }
                            }
                        }
                        node = root.SelectSingleNode("/Users/设备维护人员");
                        if (node != null)
                        {
                            for (int i = 0; i < node.ChildNodes.Count; i++)
                            {
                                //先转换 如果成功再加入
                                try
                                {
                                    if (node.ChildNodes[i].Name != "")
                                        maintain.Add(node.ChildNodes[i].Name);
                                }
                                catch (Exception)
                                {
                                }
                            }
                        }
                        node = root.SelectSingleNode("/Users/系统维护人员");
                        if (node != null)
                        {
                            for (int i = 0; i < node.ChildNodes.Count; i++)
                            {
                                //先转换 如果成功再加入
                                try
                                {
                                    if (node.ChildNodes[i].Name != "")
                                        sysdevelop.Add(node.ChildNodes[i].Name);
                                }
                                catch (Exception)
                                {
                                }
                            }
                        }
                    }
                }
                return true;
            }
            catch (Exception e)
            {
                string tmpErr = e.ToString();
                errlist.Add("打开用户权限文件异常!");
                clear();
                return false;
            }
        }
    }
    #endregion
    #region 消息管理
    /// <summary>
    /// 消息等级
    /// 不同的等级用不同的处理方法
    /// </summary>
    public enum EMessageLevel
    {
        ERROR = 0,//错误,该流程必须终止
        ALARM = 1,//报警,用户可以通过操作来取消
        NOTE = 2, //普通的提示消息
        OPERATE =3 //操作提示
    }
    /// <summary>
    /// 消息数据
    /// </summary>
    public class CMessageData
    {
        public string note = "";//备注
        public string msg = "";//内容
        public string time = "";//触发的时间
        public string sendor = "";//消息发送者
        public EMessageLevel lv = EMessageLevel.NOTE;//消息等级
        public CMessageData(string str, EMessageLevel lv)
        {
            msg = str;
            time = DateTime.Now.ToLongTimeString();
            this.lv = lv;
        }
        /// <summary>
        /// 返回等级字符串
        /// </summary>
        public string MessageLevel
        {
            get
            {
                return lv.ToString();
            }
        }
        public override string ToString()
        {
            return "时间:" + time + "  等级:" + lv.ToString() + "  内容:" + msg;
        }
    }
    /// <summary>
    /// 消息管理类,其他的线程可以不断的读取这个消息 
    /// 用于刷新模块消息到界面
    /// </summary>
    public class CMessageManager
    {
        //消息数据
        private List<CMessageData> data = new List<CMessageData>();
        private object lockObj = new object();
        private int maxMsg = 500;
        public CMessageManager(int maxMsg = 500)
        {
            this.maxMsg = maxMsg;
        }
        /// <summary>
        /// 保存消息
        /// </summary>
        /// <param name="fn"></param>
        public void save(string fn)
        {

        }
        /// <summary>
        /// 生成一个字符串消息
        /// </summary>
        /// <param name="msg">内容</param>
        /// <param name="level">等级</param>
        /// <returns></returns>
        public static string makeMessageString(string msg, EMessageLevel level = EMessageLevel.NOTE)
        {
            CMessageData tmp = new CMessageData(msg, level);
            return tmp.ToString();
        }
        /// <summary>
        /// 添加信息
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="level"></param>
        public void addMessage(string msg, EMessageLevel level = EMessageLevel.NOTE)
        {
            if (msg != "")
            {
                CMessageData tmp = new CMessageData(msg, level);
                lock (lockObj)
                {
                    if (data.Count > maxMsg)
                    {
                        data.RemoveAt(0);
                    }
                    data.Add(tmp);
                }
            }
        }
        //public CMessageData[] GetMessageData()
        //{
        //    lock (lockObj)
        //    {
        //        if (data.Count > 0)
        //        {
        //            CMessageData[] msg = data[0];
        //            data.RemoveAt(0);
        //            return msg;
        //        }
        //        else
        //        {
        //            return null;
        //        }
        //    }
        //}
        /// <summary>
        /// 返回一条消息
        /// </summary>
        /// <returns></returns>
        public CMessageData GetMessageData()
        {
            lock (lockObj)
            {
                if (data.Count > 0)
                {
                    CMessageData msg = data[0];
                    data.RemoveAt(0);
                    return msg;
                }
                else
                {
                    return null;
                }
            }
        }
        /// <summary>
        /// 获取消息,拿一条就会删除一条.
        /// </summary>
        /// <returns></returns>
        public string GetMessageStr()
        {
            lock (lockObj)
            {
                if (data.Count > 0)
                {
                    string msg = data[0].ToString();
                    data.RemoveAt(0);
                    return msg;
                }
                else
                {
                    return "";
                }
            }
        }
        /// <summary>
        /// 获取消息,拿一条就会删除一条.
        /// </summary>
        /// <returns></returns>
        public List<string> getMessageList()
        {
            lock (lockObj)
            {
                List<string> list = new List<string>();
                foreach (var item in data)
                {
                    string msg = data[0].ToString();
                    list.Add(msg);
                }
                data.Clear();
                return list;
            }
        }
        /// <summary>
        /// 清空所有消息
        /// </summary>
        public void clearMessage()
        {
            lock (lockObj)
            {
                data.Clear();
            }
        }
    }
    #endregion
    /// <summary>
    /// 下降沿
    /// </summary>
    public class CFtriger
    {
        private bool oldvalue = false;
        public bool Q(bool value)
        {
            if (value == true)
            {
                oldvalue = true;
            }
            if (oldvalue == true && value == false)
            {
                oldvalue = false;
                return true;
            }
            else
            {
                return false;
            }
        }
    }
    /// <summary>
    /// 产生一个下降沿
    /// </summary>
    public class CRtriger
    {
        private bool oldvalue = true;
        public bool Q(bool value)
        {
            if (value == false)
            {
                oldvalue = false;
            }
            if (oldvalue == false && value == true)
            {
                oldvalue = true;
                return true;
            }
            else
            {
                return false;
            }
        }
    }
    /// <summary>
    /// 循环定时器
    /// </summary>
    public class CDelay
    {
        private int starttimeMS = 0;
        private int starttimeSe = 0;
        private int starttimemin = 0;
        private long TargetTime = 0;
        public CDelay()
        {
            starttimeMS = starttimeSe = starttimemin = 0;
            TargetTime = 0;
        }
        /// <summary>
        /// 定时时间
        /// </summary>
        /// <param name="targettime"></param>
        public void SetTime(long targettime)
        {
            starttimeMS = DateTime.Now.Millisecond;
            starttimeSe = DateTime.Now.Second;
            starttimemin = DateTime.Now.Minute;
            TargetTime = targettime;
        }
        /// <summary>
        /// 循环检测是否时间到了
        /// </summary>
        /// <returns></returns>
        public bool TimeOut
        {
            get
            {
                int minit = 0;
                if (DateTime.Now.Minute >= starttimemin)
                {
                    minit = DateTime.Now.Minute - starttimemin;
                }
                else
                {
                    minit = 60 - starttimemin + DateTime.Now.Minute;
                }
                if ((minit * 60000 + (DateTime.Now.Second - starttimeSe) * 1000 + (DateTime.Now.Millisecond - starttimeMS)) > TargetTime)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
    }

    /// <summary>
    /// 保存
    /// </summary>
    public static class CDebug
    {
        public static CLogManager log = new CLogManager();//全局
    }
    /// <summary>
    /// 消息数据
    /// </summary>
    public class CLogMessage
    {
        public string time = "";
        public string type = "";
        public string txt = "";
    }
    /// <summary>
    /// 消息的类型
    /// </summary>
    public enum ELogType
    {
        ERROR = 0,
        ALARM = 1,
        NOTE = 3,
        ACTION = 4,
        MESSAGE = 5
    }
    /// <summary>
    /// 全局消息管理器
    /// 会自动保存到LOG文件中。
    /// </summary>
    public class CLogManager
    {
        List<CLogMessage> data = new List<CLogMessage>();
        int saveLenth = 1000;//当满了100条后 就开始保存一次。
        object lockData = new object();
        ~CLogManager()
        {
            save();
        }
        /// <summary>
        /// 添加消息
        /// </summary>
        /// <param name="msg">消息内容</param>
        /// <param name="type">消息类型</param>
        public void add(string msg, ELogType type = ELogType.MESSAGE)
        {
            if (msg == "")
                return;
            CLogMessage d = new CLogMessage();
            d.time = DateTime.Now.ToString("HH:MM");
            switch (type)
            {
                case ELogType.ERROR:
                    d.type = "错误";
                    break;
                case ELogType.ALARM:
                    d.type = "报警";
                    break;
                case ELogType.NOTE:
                    d.type = "提示";
                    break;
                case ELogType.ACTION:
                    d.type = "动作";
                    break;
                case ELogType.MESSAGE:
                    d.type = "消息";
                    break;
                default:
                    d.type = "提示";
                    break;
            }
            d.txt = msg;
            lock (lockData)
            {
                data.Add(d);
            }
            if (data.Count > saveLenth)
            {
                save();
            }
        }
        /// <summary>
        /// 保存
        /// </summary>
        public void save()
        {
            if (!File.Exists(@"log.txt"))
            {
                File.Create(@"log.txt");
            }
            try
            {
                lock (lockData)
                {
                    StreamWriter FileWriter = new StreamWriter("log.txt", true); //写文件
                    foreach (var item in data)
                    {
                        string str = "时间:" + item.time + "   类型:" + item.type + "   内容:" + item.txt;
                        FileWriter.WriteLine(str);//将字符串写入
                    }
                    FileWriter.Close(); //关闭StreamWriter对象
                    data.Clear();
                }
            }
            catch (Exception)
            {
            }
        }
    }

}
